package cn.huaqingcheng.tool.core.model;

import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;

import java.util.Iterator;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Stream;

/**
 * Tuple
 */
@SuppressWarnings("unused")
public interface Tuple {

    /**
     * 双元素元组, 和 {@code reactor.util.function.Tuples#of(Object, Object)} 区别在于不强制要求元素非空
     */
    @Contract("_, _ -> new")
    static <A, B> @NotNull Tuple2<A, B> of(A a, B b) {
        return new Tuple2<>(a, b);
    }

    /**
     * 三元素元组, 和 {@code reactor.util.function.Tuples#of(Object, Object, Object)} 区别在于不强制要求元素非空
     */
    @Contract("_, _, _ -> new")
    static <A, B, C> @NotNull Tuple3<A, B, C> of(A a, B b, C c) {
        return new Tuple3<>(a, b, c);
    }

    /**
     * 四元素元组, 并不推荐使用
     */
    @Contract("_, _, _, _ -> new")
    static <A, B, C, D> @NotNull Tuple4<A, B, C, D> of(A a, B b, C c, D d) {
        return new Tuple4<>(a, b, c, d);
    }

    /**
     * 类型安全的迭代器
     *
     * @see Tuple2#iterator()
     */
    @Contract(value = "_ -> new", pure = true)
    static <T> @NotNull Iterator<T> iterator(@NotNull Tuple2<T, T> tuple) {
        return new ArrayIterator<>(tuple.a, tuple.b);
    }

    /**
     * 类型安全的迭代器
     *
     * @see Tuple3#iterator()
     */
    @Contract(value = "_ -> new", pure = true)
    static <T> @NotNull Iterator<T> iterator(@NotNull Tuple3<T, T, T> tuple) {
        return new ArrayIterator<>(tuple.a, tuple.b, tuple.c);
    }

    /**
     * 类型安全的迭代器
     *
     * @see Tuple4#iterator()
     */
    @Contract(value = "_ -> new", pure = true)
    static <T> @NotNull Iterator<T> iterator(@NotNull Tuple4<T, T, T, T> tuple) {
        return new ArrayIterator<>(tuple.a, tuple.b, tuple.c, tuple.d);
    }

    /**
     * 类型安全的转换器
     *
     * @return 可能传递 null
     */
    @SuppressWarnings("ReturnOfNull")
    @Contract(value = "null, _ -> null; !null, null -> fail; !null, !null -> new", pure = true)
    static <T, R> Tuple2<R, R> map(Tuple2<T, T> tuple, Function<T, R> map) {
        if (tuple == null) {
            return null;
        }
        Objects.requireNonNull(map);
        return new Tuple2<>(
            map.apply(tuple.a),
            map.apply(tuple.b)
        );
    }

    /**
     * 类型安全的转换器
     *
     * @return 可能传递 null
     */
    @SuppressWarnings("ReturnOfNull")
    @Contract(value = "null, _ -> null; !null, null -> fail; !null, !null -> new", pure = true)
    static <T, R> Tuple3<R, R, R> map(Tuple3<T, T, T> tuple, Function<T, R> map) {
        if (tuple == null) {
            return null;
        }
        Objects.requireNonNull(map);
        return new Tuple3<>(
            map.apply(tuple.a),
            map.apply(tuple.b),
            map.apply(tuple.c)
        );
    }

    /**
     * 类型安全的转换器
     *
     * @return 可能传递 null
     */
    @SuppressWarnings("ReturnOfNull")
    @Contract(value = "null, _ -> null; !null, null -> fail; !null, !null -> new", pure = true)
    static <T, R> Tuple4<R, R, R, R> map(Tuple4<T, T, T, T> tuple, Function<T, R> map) {
        if (tuple == null) {
            return null;
        }
        Objects.requireNonNull(map);
        return new Tuple4<>(
            map.apply(tuple.a),
            map.apply(tuple.b),
            map.apply(tuple.c),
            map.apply(tuple.d)
        );
    }

    /**
     * 元素类型相同的元组, 转 {@link Stream}
     */
    static <T> @NotNull Stream<T> stream(Tuple2<T, T> tuple) {
        Objects.requireNonNull(tuple);
        return Stream.of(tuple.a, tuple.b);
    }

    /**
     * 元素类型相同的元组, 转 {@link Stream}
     */
    static <T> @NotNull Stream<T> stream(Tuple3<T, T, T> tuple) {
        Objects.requireNonNull(tuple);
        return Stream.of(tuple.a, tuple.b, tuple.c);
    }

    /**
     * 元素类型相同的元组, 转 {@link Stream}
     */
    static <T> @NotNull Stream<T> stream(Tuple4<T, T, T, T> tuple) {
        Objects.requireNonNull(tuple);
        return Stream.of(tuple.a, tuple.b, tuple.c, tuple.d);
    }

    // 实现类

    record Tuple2<A, B>(A a, B b) implements Iterable<Object> {

        /**
         * 类型不安全的迭代器
         */
        @NotNull
        @Override
        public Iterator<Object> iterator() {
            return new ArrayIterator<>(a, b);
        }

    }

    record Tuple3<A, B, C>(A a, B b, C c) implements Iterable<Object> {

        @NotNull
        @Override
        public Iterator<Object> iterator() {
            return new ArrayIterator<>(a, b, c);
        }

    }

    record Tuple4<A, B, C, D>(A a, B b, C c, D d) implements Iterable<Object> {

        @NotNull
        @Override
        public Iterator<Object> iterator() {
            return new ArrayIterator<>(a, b, c, d);
        }

    }

}
